from bpy.types import PropertyGroup, Collection
from bpy.props import FloatProperty, BoolProperty, IntProperty, PointerProperty
from ..updaters.props_update_particles import particles_props_update
from ....libs.functions.get_common_vars import get_common_vars
from .anim.props_physics_anim import ActiveEmitterPhysicsAnimProps



class ActiveEmitterPhysicsProps(PropertyGroup):

    """ Propiedades guardadas en el active_emitter_item.physics.x """

    # estas van a nivel grupo no de item:
    anim: PointerProperty(type=ActiveEmitterPhysicsAnimProps)

    # Integration:
    timestep: FloatProperty(
        name="Timestep",
        description="The simulation timestep per frame (seconds per frame)",
        default=0.04,
        soft_min=0.01,
        min=0,
        soft_max=10.0,
        max=100.0,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_integration_sect", "timestep")
    )
    subframes: IntProperty(
        name="Subframes",
        description="Subframes to simulate for improved stability and finer granularity simulation (dt = timestep / (subframes + 1))",
        min=0,
        max=1000,
        default=4,
        update=lambda self, context: particles_props_update(self, context, "global_mode_integration_sect", "subframes")
    )
    use_adaptive_subframes: BoolProperty(
        name="Adaptive Subframe",
        description="Automatically set the number of subframes",
        default=False,
        update=lambda self, context: particles_props_update(self, context, "global_mode_integration_sect", "use_adaptive_subframes")
    )
    courant_target: FloatProperty(
        name="Adaptive Subframe Threshold",
        description="The relative distance a particle can move before requiring more subframes (target Courant number); 0.01 to 0.3 is the recomended range",
        min=0,
        max=10,
        default=0.2,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_integration_sect", "courant_target")
    )

    # Physics:
    mass: FloatProperty(
        name="Mass",
        description="Mass of the particles",
        default=0.1,
        min=0,
        soft_min=0.01,
        max=100000,
        unit='MASS',
        precision=4,
        update=lambda self, context: particles_props_update(self, context, "global_mode_physics_sect", "mass")
    )

    use_multiply_size_mass: BoolProperty(
        name="Multiply by size",
        description="Multiply mass by particle size",
        default=False,
        update=lambda self, context: particles_props_update(self, context, "global_mode_physics_sect", "use_multiply_size_mass")
    )

    stiffness: FloatProperty(
        name="Stiffness",
        description="How incomprensible the fluid is (speed of sound) (higher values more chaotic)",
        min=0,
        soft_max=10,
        max=1000.0,
        default=0.5,
        precision=4,
        update=lambda self, context: particles_props_update(self, context, "global_mode_physics_sect", "stiffness")
    )
    linear_viscosity: FloatProperty(
        name="Viscosity",
        description="Linear Viscosity",
        min=0,
        soft_max=10,
        max=100.0,
        default=0.5,
        precision=4,
        update=lambda self, context: particles_props_update(self, context, "global_mode_physics_sect", "linear_viscosity")
    )
    drag_factor: FloatProperty(
        name="Drag",
        default=0.02, 
        min=0, 
        max=1,
        update=lambda self, context: particles_props_update(self, context, "global_mode_physics_sect", "drag_factor")
    )
    damping: FloatProperty(
        name="Damping",
        default=0.02,
        min=0, 
        max=1,
        update=lambda self, context: particles_props_update(self, context, "global_mode_physics_sect", "damping")
    )
    use_size_deflect: BoolProperty(
        name="Size Deflect",
        description="Use particle's size in deflection",
        default=False,
        update=lambda self, context: particles_props_update(self, context, "global_mode_physics_sect", "use_size_deflect")
    )
    
    # collisions collection:
    collision_coll: PointerProperty(
        type=Collection,
        update=lambda self, context: particles_props_update(self, context, "global_mode_physics_sect", "collision_coll")
    )

    # Advanced Behavior:
    repulsion: FloatProperty(
        name="Repulsion Factor",
        description="How strongly the fluid tries to keep from clustering (factor of stiffness)",
        min=0,
        soft_max=2,
        max=100.0,
        default=1,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_b_sect", "repulsion")
    )
    stiff_viscosity: FloatProperty(
        name="Stiff Viscosity",
        description="Creates viscosity for expanding fluid",
        min=0,
        soft_max=2,
        max=100.0,
        default=1,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_b_sect", "stiff_viscosity")
    )
    
    # "fluid_radius", esta en emission (lo necesitaba para soft start).
    prev_fluid_radius: FloatProperty(
                                    default=1,
                                    min=0, 
                                    soft_max=2,
                                    max=20,
                                )
    fluid_radius: FloatProperty(
                                    name="Radius",
                                    default=1,
                                    min=0, 
                                    soft_max=2,
                                    max=20,
                                    update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_b_sect", "fluid_radius")
                                )

    rest_density: FloatProperty(
        name="Rest Density",
        description="Fluid rest density",
        min=0,
        soft_max=2,
        max=10000.0,
        default=1,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_b_sect", "rest_density")
    )

    def filter_collection(self, coll):
        return True


    collection: PointerProperty(
        name="Effector Collection",
        description="Limit effectors to this collection",
        type=Collection,
        poll=filter_collection,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "collection")
    )

    gravity: FloatProperty(
        name="Gravity",
        description="Global gravity weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "gravity")
    )
    all: FloatProperty(
        name="All",
        description="All effector`s weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "all")
    )
    force: FloatProperty(
        name="Force",
        description="Force effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "force")
    )
    vortex: FloatProperty(
        name="Vortex",
        description="Vortex effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "vortex")
    )
    magnetic: FloatProperty(
        name="Magnetic",
        description="Magnetic effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "magnetic")
    )
    harmonic: FloatProperty(
        name="Harmonic",
        description="Harmonic effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "harmonic")
    )
    charge: FloatProperty(
        name="Charge",
        description="Charge effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "charge")
    )
    lennardjones: FloatProperty(
        name="Lennard-jones",
        description="Lennard-jones effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "lennardjones")
    )
    wind: FloatProperty(
        name="Wind",
        description="Wind effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "wind")
    )
    curve_guide: FloatProperty(
        name="Curve Guide",
        description="Curve Guide effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "curve_guide")
    )
    texture: FloatProperty(
        name="Texture",
        description="Texture effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "texture")
    )
    smokeflow: FloatProperty(
        name="Fluid Flow",
        description="Fluid Flow effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "smokeflow")
    )
    turbulence: FloatProperty(
        name="Turbulence",
        description="Turbulence effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "turbulence")
    )
    drag: FloatProperty(
        name="Drag",
        description="Drag effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "drag")
    )
    boid: FloatProperty(
        name="Boid",
        description="Boid effector weight",
        default=1,
        soft_max=1,
        soft_min=0,
        max=200,
        min=-200,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_advanced_field_weights_sect", "boid")
    )


    def get_default_properties(self, target_prop):
        for prop in self.bl_rna.properties:
            if prop.identifier == target_prop:
                if hasattr(prop, "default"):
                    return prop.default